package org.sction.action.filter;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import net.sf.json.JSON;
import net.sf.json.JsonConfig;

import org.apache.log4j.Logger;
import org.apache.shiro.authz.UnauthorizedException;
import org.codehaus.jackson.map.ObjectMapper;
import org.sction.action.annotation.Action;
import org.sction.action.annotation.Result;
import org.sction.action.annotation.ReturnType;
import org.sction.action.core.ActionUtils;
import org.sction.action.core.BaseAction;
import org.sction.bean.ExcelBean;
import org.sction.bean.FileBean;
import org.sction.cache.CacheManager;
import org.sction.manager.file.ToExcelUtils;
import org.sction.security.log.AccessLog;
import org.sction.security.log.AccessLogBaseImpl;
import org.sction.security.permission.PermissionAssert;
import org.sction.security.permission.ShiroPermissionAssert;
import org.sction.util.DateJsonValueProcessor;
import org.sction.util.FileUtils;
import org.sction.util.JSONUtils;
import org.sction.util.SQLDateJsonValueProcessor;
import org.sction.util.StringUtils;
import org.sction.util.TimestampJsonValueProcessor;


/**
 * encoding ajaxEncoding dispatchMethod loginIdKey loginNameKey<br/>
 * web.xml配置<br/>
 * &lt;!--Action过滤器--&gt;<br/>
 * &lt;filter&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-name&gt;action&lt;/filter-name
 * &gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-class&gt;com.aide.action.
 * filter.ActionFilter&lt;/filter-class&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- 如果结合spring使用
 * 请配置objectFactiory为spring 默认为none无 --&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;
 * param-name&gt;objectFactory&lt;/param-name&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;
 * param-value&gt;spring&lt;/param-value&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--
 * 使用@Namespace/@Controller.do?action=@Action 格式访问Action 时的参数名,默认action --&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;
 * param-name&gt;action&lt;/param-name&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;
 * param-value&gt;action&lt;/param-value&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- 访问日志级别 INFO WARN ERROR DEBUG
 * FATAL OFF 默认为OFF 不显示访问日志--&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;init-param&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;
 * param-name&gt;logLevel&lt;/param-name&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;
 * param-value&gt;INFO&lt;/param-value&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/init-param&gt;<br/>
 * &lt;/filter&gt;<br/>
 * &lt;!--配置action访问后缀 *.do; *.action 或*.自定义--&gt;<br/>
 * &lt;filter-mapping&gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-name&gt;action&lt;/filter-name
 * &gt;<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;*.do&lt;/url-pattern&
 * gt;<br/>
 * &lt;/filter-mapping&gt;<br/>
 * 
 * 
 * @author 作者：sorc
 * @version 创建时间：2012-2-17 下午12:48:06
 */
public class ActionFilter implements Filter {

	private static final Logger logger = Logger.getLogger(ActionFilter.class);
	static final long serialVersionUID = 1L;
	public ServletContext servletContext;
	protected FilterConfig filterConfig;
	private static String authzAssertClass = null;
	private static String accessLogClass = null;
	private static String objectFactory = "spring";
	private static String userSessionKey = "user";
	private static String encoding = "UTF-8";
	private static String ajaxEncoding = "UTF-8";

	private static String ajaxHeaderName = "X-Requested-With";
	private static String ajaxHeaderValue = "XMLHttpRequest";

	private static String authzErrorPage = "authz_error.jsp";
	private static String errorPage = "error.jsp";

	private static PermissionAssert authzAssert = null;
	private static AccessLog accessLog = new AccessLogBaseImpl();

	public ActionFilter() {
		servletContext = null;
		filterConfig = null;
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		logger.info("初始化Action过滤器参数...");
		this.filterConfig = filterConfig;
		servletContext = filterConfig.getServletContext();

		ActionUtils.objectFactory = StringUtils.emptyConvert(
				filterConfig.getInitParameter("objectFactory"), objectFactory);
		authzErrorPage = StringUtils
				.emptyConvert(filterConfig.getInitParameter("authzErrorPage"),
						authzErrorPage);
		errorPage = StringUtils.emptyConvert(
				filterConfig.getInitParameter("errorPage"), errorPage);
		encoding = StringUtils.emptyConvert(
				filterConfig.getInitParameter("encoding"), encoding);
		ajaxEncoding = StringUtils.emptyConvert(
				filterConfig.getInitParameter("ajaxEncoding"), ajaxEncoding);
		ajaxHeaderName = StringUtils
				.emptyConvert(filterConfig.getInitParameter("ajaxHeaderName"),
						ajaxHeaderName);
		ajaxHeaderValue = StringUtils.emptyConvert(
				filterConfig.getInitParameter("ajaxHeaderValue"),
				ajaxHeaderValue);
		ActionUtils.userSessionKey = StringUtils
				.emptyConvert(filterConfig.getInitParameter("userSessionKey"),
						userSessionKey);
		accessLogClass = StringUtils
				.emptyConvert(filterConfig.getInitParameter("accessLogClass"),
						accessLogClass);

		authzAssertClass = StringUtils.emptyConvert(
				filterConfig.getInitParameter("authzAssertClass"),
				authzAssertClass);
		if (accessLogClass != null) {
			try {
				Class<?> clazz = Class.forName(accessLogClass);
				Object alobj = clazz.newInstance();
				if (alobj instanceof AccessLog) {
					accessLog = (AccessLog) alobj;
				} else {
					logger.error("日志访问类配置错误，请实现AccessLog接口");
				}
			} catch (Exception e) {
				logger.error("日志访问类配置错误，类不存在或没有发现空构造函数！", e);
			}
		}
		if (authzAssertClass != null) {
			if ("shiro".equals(authzAssertClass)) {
				authzAssert = new ShiroPermissionAssert();
			} else {
				try {
					Class<?> clazz = Class.forName(authzAssertClass);
					Object paobj = clazz.newInstance();
					if (paobj instanceof PermissionAssert) {
						authzAssert = (PermissionAssert) paobj;
					} else {
						logger.error("权限断言类配置错误，请实现AccessLog接口");
					}
				} catch (Exception e) {
					logger.error("权限断言类配置错误，类不存在或没有发现空构造函数！", e);
				}
			}
		}
	}

	@SuppressWarnings("finally")
	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		// if (!AideSNManager.isAuthorized()) {
		// response.reset();
		// response.sendRedirect(request.getContextPath() + "/sn.jsp");
		// return;
		// }

		// 处理编码格式
		if (isAjaxRequest(request) && isEnableEncoding(ajaxEncoding)) {
			request.setCharacterEncoding(ajaxEncoding);
			response.setCharacterEncoding(ajaxEncoding);
			request.getParameter(ajaxHeaderName); // for lock
													// encoding
		} else if (isEnableEncoding(encoding)) {
			request.setCharacterEncoding(encoding);
			response.setCharacterEncoding(encoding);
		}
		// 初始化日志中的用户编号、用户名、访问IP、Cookie及浏览器信息

		// 加载控制器
		Object controller = ActionUtils
				.loadController(request.getServletPath());

		// 获取控制器Key和ActionKey 并记录到日志
		String controllerKey = ActionUtils.pathControllerKey(request);
		String actionKey = ActionUtils.pathActionKey(request);

		if (controller == null) {
			String error = "Controller[" + controllerKey + "] not found!";
			logger.error(error);
			request.setAttribute("_error_", "请求错误：没有此模块[" + controllerKey + "]");
			request.setAttribute("_exception_", null);
			request.getRequestDispatcher(request.getContextPath() + errorPage)
					.forward(request, response);
			return;
		}

		if (controller instanceof BaseAction) {
			try {
				Method initMethod = controller.getClass().getMethod("init",
						ServletContext.class, ServletRequest.class,
						ServletResponse.class);
				initMethod.invoke(controller, servletContext, servletRequest,
						servletResponse);
			} catch (Exception e) {
				logger.error("初始化BaseAction上下文错误", e);
				request.setAttribute("_error_", "初始化BaseAction上下文错误");
				request.setAttribute("_exception_", e.getCause());
				request.getRequestDispatcher(
						request.getContextPath() + errorPage).forward(request,
						response);
				return;
			}
		}
		// 初始化Controller参数
		ActionUtils.initControllerParameters(controller, request, response,
				servletContext);
		// 加载Action
		Method action = CacheManager.getAction(controllerKey, actionKey);
		if (action == null) {
			String error = "Controller[" + controllerKey + "] Action["
					+ actionKey + "] not found!";
			logger.error(error);
			request.setAttribute("_error_", "请求错误：在模块[" + controllerKey
					+ "]中没有[" + actionKey + "]方法");
			request.setAttribute("_exception_", null);
			request.getRequestDispatcher(request.getContextPath() + errorPage)
					.forward(request, response);
			return;
		}

		Action a = action.getAnnotation(Action.class);
		Object[] params = null;
		Object urlx = null;

		// 调用Action方法
		// 开始执行Action方法体

		try {
			boolean hashPermissions = true;
			String permissions = a.permissions();
			if (permissions.length() > 0) {
				if (authzAssert != null) {
					hashPermissions = authzAssert.isPermitted(permissions);
				} else {
					logger.warn("未配置权限断言类，无法进行权限判断！请实现PermissionAssert接口并配置authzAssertClass属性为实现类的全名");
				}
			}

			if (hashPermissions) {
				if (action.getParameterTypes().length == 0) {
					// 方法执行前写日志
					accessLog.beforeLog(a, controller, action, new Object[] {});
					urlx = action.invoke(controller);
				} else {
					params = ActionUtils.initActionParameters(action,
							servletRequest, servletResponse, servletContext);
					// 方法执行前写日志
					accessLog.beforeLog(a, controller, action, params);
					urlx = action.invoke(controller, params);
				}
				// 方法执行后写日志
				accessLog.AfterLog(a, controller, action, urlx);
			} else {
				accessLog.notPermissionsLog(a, controller, action, params,
						permissions);
				request.setAttribute("_error_", "无权访问,此模块需要拥有【permissions】权限！");
				request.setAttribute("_exception_", null);
				request.getRequestDispatcher(
						request.getContextPath() + authzErrorPage).forward(
						request, response);
			}

			// 处理Action返回值
			// 开始跳转返回
			if (urlx != null) {
				// 如果返回值类型为FileBean 则下载FileBean中的文件
				if (urlx instanceof FileBean) {
					InputStream inputs = null;
					OutputStream outputs = null;
					FileBean fileBean = ((FileBean) urlx);
					String name = fileBean.getName();
					String suffix = fileBean.getSuffix();

					if (fileBean.isDown()) {
						String nameEncoding = fileBean.getNameEncoding();
						if (nameEncoding == null
								|| nameEncoding.trim().equals("")) {
							nameEncoding = encoding;
						}
						java.io.File file = fileBean.getFile();
						if (file != null && file.exists() && file.isFile()) {
							if (name == null || name.trim().equals("")) {
								name = FileUtils.getFileSimpleName(file
										.getPath());
							}
							String mimeType = fileBean.getMimeType();
							if (mimeType == null || mimeType.trim().equals("")) {
								mimeType = "application/octet-stream;";
							}

							Long fileSize = file.length();
							response.reset();
							response.setCharacterEncoding(encoding);
							response.setContentType(mimeType);

							if (fileBean.isStream()) {
								String target = request.getParameter("target");
								int targetInt = 0;
								RandomAccessFile raf = null;
								int totalByte = 0;
								try {
									raf = new RandomAccessFile(file, "r");
									totalByte = (int) raf.length();
									if (target != null && !"".equals(target)) {
										try {
											targetInt = Integer
													.parseInt(target);
											byte[] headData = new byte[] { 'F',
													'L', 'V', 1, 1, 0, 0, 0, 9,
													0, 0, 0, 9 }; // 拖动时间轴后的response中头信息需写入该字节
											response.getOutputStream().write(
													headData);
											response.setContentLength(totalByte
													- targetInt + 13);
										} catch (NumberFormatException e) {
											targetInt = 0;
										}
									} else {
										response.setContentLength(totalByte
												- targetInt);
									}
									raf.skipBytes(targetInt);// 跳过时间轴前面的字节;
									byte[] b = new byte[4096];
									while (raf.read(b) != -1) {
										response.getOutputStream().write(b);
									}
									response.getOutputStream().flush();

								} catch (Exception e) {
									String simplename = e.getClass()
											.getSimpleName();
									if (!"ClientAbortException"
											.equals(simplename)) {
										e.printStackTrace();
									}// web端拖动时间轴总有连接被重置的异常，暂时还不知如何解决，可以此方式不输出异常
								} finally {
									if (raf != null) {
										raf.close();
									}
								}
							} else {
								response.addHeader(
										"Content-Disposition",
										"attachment; filename=\""
												+ URLEncoder.encode(name
														+ suffix, nameEncoding)
												+ "\"");
								response.setHeader("Content-Length", ""
										+ fileSize);

								outputs = response.getOutputStream();
								inputs = new FileInputStream(file);
								byte[] buf = new byte[1024];
								int len = 0;
								while ((len = inputs.read(buf)) > 0)
									outputs.write(buf, 0, len);
								if (inputs != null) {
									inputs.close();
								}
								if (outputs != null) {
									outputs.close();
								}
							}
						} else if (fileBean.getBin() != null) {
							response.addHeader(
									"Content-Disposition",
									"attachment; filename=\""
											+ URLEncoder.encode(name + suffix,
													nameEncoding) + "\"");
							response.setHeader("Content-Length",
									"" + fileBean.getBin().length);

							outputs = response.getOutputStream();
							outputs.write(fileBean.getBin());
							if (outputs != null) {
								outputs.close();
							}
						} else {
							// 如果FileBean中的文件不存在
							response.setCharacterEncoding("UTF-8");
							PrintWriter out = response.getWriter();
							out.println("<html>");
							out.println("<head>");
							out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
							out.println("</head>");
							out.println("<body>");
							out.println("<script type=\"text/javascript\">");
							out.println("alert('服务器不存在此文件:" + name + suffix
									+ "');");
							out.println("history.back();");
							out.println("</script>");
							out.println("</body>");
							out.println("</html>");
							out.flush();
							out.close();
						}
					} else {
						// 如果FileBean中的文件不允许下载
						String msg = fileBean.getMsg();
						response.setCharacterEncoding("UTF-8");
						PrintWriter out = response.getWriter();
						out.println("<html>");
						out.println("<head>");
						out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
						out.println("</head>");
						out.println("<body>");
						out.println("<script type=\"text/javascript\">");
						out.println("alert('" + (msg == null ? "文件不许下载。" : msg)
								+ "(" + name + suffix + ")');");
						out.println("history.back();");
						out.println("</script>");
						out.println("</body>");
						out.println("</html>");
						out.flush();
						out.close();
					}
				} else if (urlx instanceof ExcelBean) {
					OutputStream outputs = null;
					ExcelBean toExcelBean = ((ExcelBean) urlx);
					logger.info("导出Excel：" + toExcelBean.getName());
					if (toExcelBean.getSheets() != null) {
						String mimeType = "application/vnd.ms-excel;";
						String nameEncoding = toExcelBean.getNameEncoding();
						if (nameEncoding == null
								|| nameEncoding.trim().equals("")) {
							nameEncoding = encoding;
						}
						response.reset();
						response.setCharacterEncoding(encoding);
						response.setContentType(mimeType);
						response.addHeader(
								"Content-Disposition",
								"attachment; filename=\""
										+ URLEncoder.encode(
												toExcelBean.getName(),
												nameEncoding) + "\"");
						// response.setHeader("Content-Length", "" + fileSize);
						outputs = response.getOutputStream();
						ToExcelUtils.createWorkbook(toExcelBean.isXlsx(),
								toExcelBean.getSheets(),
								toExcelBean.getToExcelRender()).write(outputs);
						if (outputs != null) {
							outputs.close();
						}
					} else {
						logger.error("查询Excel数据为Null");
					}
				} else if (urlx instanceof Boolean || urlx instanceof Integer
						|| urlx instanceof Float) {
					PrintWriter out = response.getWriter();
					response.setContentType("text/html; charset=" + encoding);
					response.setHeader("Cache-Control", "no-cache"); // 取消浏览器缓存
					out.print(urlx);
					out.flush();
					out.close();
				} else if (urlx instanceof JSON) {
					PrintWriter out = response.getWriter();
					response.setContentType("application/json; charset="
							+ encoding);
					response.setHeader("Cache-Control", "no-cache");
					out.print(urlx);
					out.flush();
					out.close();
				} else {
					ReturnType rt = a != null ? a.returnType()
							: ReturnType.OUTPUT;

					switch (rt) {
					case FORWARD:// 跳转页面
						request.getRequestDispatcher((String) urlx).forward(
								request, response);
						break;
					case REDIRECT:// 重定向页面
						response.sendRedirect((String) urlx);
						break;
					case RESULTS:// 按results映射集跳转或重定向页面
						Result[] results = a.results();
						boolean flag = false;
						for (Result result : results) {
							if (result.name().equalsIgnoreCase(urlx.toString())) {
								flag = true;
								if (result.type().equals(Result.Type.FORWARD)) {
									request.getRequestDispatcher(
											result.location()).forward(request,
											response);
								} else {
									response.sendRedirect(result.location());
								}
								break;
							}
						}
						if (!flag) {// 如果返回了没有响应映射的地址则报错信息输出到页面
							PrintWriter out = response.getWriter();
							response.setContentType("text/html; charset="
									+ encoding);
							response.setHeader("Cache-Control", "no-cache"); // 取消浏览器缓存
							out.println("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset="
									+ encoding
									+ "\"></head>"
									+ "<body>未定义：result:" + urlx + "<br/>");
							out.println("格式：<br/>");
							out.println("@Action(returnType = ReturnType.RESULTS,<br/> results = { @Result(name = \"index\", location = \"index.jsp\"),<br/>@Result(name = \"test\", location = \"test.jsp\") })");
							out.println("</body></html>");
							out.flush();
							out.close();
						}
						break;
					case XML: // 使用JAXB2将对象转为XML输出
						response.reset();
						response.setCharacterEncoding("UTF-8");
						response.setContentType("text/xml; charset=utf-8");
						JAXBContext context = JAXBContext.newInstance(urlx
								.getClass());
						Marshaller marshaller = context.createMarshaller();
						marshaller.setProperty(
								Marshaller.JAXB_FORMATTED_OUTPUT, true);
						marshaller.setProperty(Marshaller.JAXB_ENCODING,
								System.getProperty("file.encoding"));
						marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
						PrintWriter out1 = response.getWriter();
						marshaller.marshal(urlx, out1);
						out1.flush();
						out1.close();
						break;
					case JSON: //
						response.reset();
						PrintWriter out3 = response.getWriter();
						response.setContentType("application/json; charset="
								+ encoding);
						response.setHeader("Cache-Control", "no-cache");
						ObjectMapper om = new ObjectMapper();
						out3.print(om.writeValueAsString(urlx));
						out3.flush();
						out3.close();
						break;
					default:// 如果返回值为字符串默认直接页面输出返回值 否则将对象转为JSON输出
						if (urlx instanceof String) {
							response.reset();
							PrintWriter out4 = response.getWriter();
							response.setContentType("text/html; charset="
									+ encoding);
							response.setHeader("Cache-Control", "no-cache"); // 取消浏览器缓存
							out4.print(urlx);
							out4.flush();
							out4.close();
						} else {// 使用JSONUtils将对象转为JSON字符串输出

							response.reset();
							response.setContentType("application/json; charset="
									+ encoding);
							response.setHeader("Cache-Control", "no-cache");

							PrintWriter out2 = response.getWriter();
							if (urlx instanceof String) {
								out2.print(urlx);
								out2.flush();
								out2.close();
								break;
							}
							JsonConfig jsonConfig = new JsonConfig();
							jsonConfig.registerJsonValueProcessor(Date.class,
									new DateJsonValueProcessor());
							jsonConfig.registerJsonValueProcessor(
									java.sql.Date.class,
									new SQLDateJsonValueProcessor());
							jsonConfig.registerJsonValueProcessor(
									java.sql.Timestamp.class,
									new TimestampJsonValueProcessor());
							JSON json = JSONUtils.toJSON(urlx, jsonConfig);
							String callback = request.getParameter("callback");
							if (callback != null && !callback.trim().equals("")
									&& callback.equals("=?")) {
								callback = callback.substring(0,
										callback.length() - 2)
										+ "(" + json.toString() + ");";
								out2.print(callback);
							} else {
								out2.print(json);
							}
							out2.flush();
							out2.close();

						}
						break;
					}
				}
			}

		} catch (Exception e) {
			if (e.getCause() instanceof UnauthorizedException) {
				request.setAttribute("_error_", "无权访问");
				request.setAttribute("_exception_", e.getCause());
				request.getRequestDispatcher(
						request.getContextPath() + authzErrorPage).forward(
						request, response);
			} else {
				request.setAttribute("_error_", "执行方法时发生错误");
				request.setAttribute("_args_", StringUtils.arryToString(params));
				request.setAttribute("_exception_", e.getCause());
				request.getRequestDispatcher(
						request.getContextPath() + errorPage).forward(request,
						response);
				logger.error("执行方法时发生错误", e);
			}
			return;
		} finally {
			if (controller instanceof BaseAction) {
				((BaseAction) controller).dispose();
			}
			return;
		}

	}

	public void destroy() {
		servletContext = null;
		filterConfig = null;
	}

	private boolean isEnableEncoding(String encoding) {
		return !"false".equalsIgnoreCase(encoding)
				&& !"none".equalsIgnoreCase(encoding);
	}

	private boolean isAjaxRequest(HttpServletRequest request) {
		return ajaxHeaderValue.equalsIgnoreCase(request
				.getHeader(ajaxHeaderName));
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		ActionFilter.encoding = encoding;
	}

	public String getAjaxEncoding() {
		return ajaxEncoding;
	}

	public void setAjaxEncoding(String ajaxEncoding) {
		ActionFilter.ajaxEncoding = ajaxEncoding;
	}

	public String getAuthzErrorPage() {
		return authzErrorPage;
	}

	public void setAuthzErrorPage(String authzErrorPage) {
		ActionFilter.authzErrorPage = authzErrorPage;
	}

	public String getErrorPage() {
		return errorPage;
	}

	public void setErrorPage(String errorPage) {
		ActionFilter.errorPage = errorPage;
	}

	public PermissionAssert getAuthzAssert() {
		return authzAssert;
	}

	public void setAuthzAssert(PermissionAssert authzAssert) {
		ActionFilter.authzAssert = authzAssert;
	}

	public AccessLog getAccessLog() {
		return accessLog;
	}

	public void setAccessLog(AccessLog accessLog) {
		ActionFilter.accessLog = accessLog;
	}

	public String getAuthzAssertClass() {
		return authzAssertClass;
	}

	public void setAuthzAssertClass(String authzAssertClass) {
		ActionFilter.authzAssertClass = authzAssertClass;
	}

	public String getAccessLogClass() {
		return accessLogClass;
	}

	public void setAccessLogClass(String accessLogClass) {
		ActionFilter.accessLogClass = accessLogClass;
	}

	public String getObjectFactory() {
		return objectFactory;
	}

	public void setObjectFactory(String objectFactory) {
		ActionFilter.objectFactory = objectFactory;
	}

	public String getUserSessionKey() {
		return userSessionKey;
	}

	public void setUserSessionKey(String userSessionKey) {
		ActionFilter.userSessionKey = userSessionKey;
	}

	public String getAjaxHeaderName() {
		return ajaxHeaderName;
	}

	public void setAjaxHeaderName(String ajaxHeaderName) {
		ActionFilter.ajaxHeaderName = ajaxHeaderName;
	}

	public String getAjaxHeaderValue() {
		return ajaxHeaderValue;
	}

	public void setAjaxHeaderValue(String ajaxHeaderValue) {
		ActionFilter.ajaxHeaderValue = ajaxHeaderValue;
	}

}
